package com.addplus.townmall.server.web.provider.serviceimpl.authoritymodule;

import com.addplus.townmall.server.api.constant.ErrorCode;
import com.addplus.townmall.server.api.constant.StringConstant;
import com.addplus.townmall.server.api.exception.ErrorException;
import com.addplus.townmall.server.api.mapper.authority.*;
import com.addplus.townmall.server.api.model.authority.MenuFunction;
import com.addplus.townmall.server.api.model.authority.RoleMenuFunction;
import com.addplus.townmall.server.api.model.authority.ext.MenuFunctionUser;
import com.addplus.townmall.server.api.model.authority.ext.RoleMenuFunctionUser;
import com.addplus.townmall.server.api.service.web.authoritymodule.MenuFunctionService;
import com.addplus.townmall.server.api.service.web.authoritymodule.RoleMenuFunctionService;
import com.addplus.townmall.server.api.utils.DataUtils;
import com.addplus.townmall.server.api.utils.MenuFunctionTreeUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.rpc.RpcContext;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 类名: MenuFunctionServiceImpl
 *
 * @author zhangjiehang
 * @version V1.0
 * @date 2017/12/4 下午1:34
 * @description 类描述: 菜单功能实现类
 */
@Service(interfaceClass = MenuFunctionService.class)
public class MenuFunctionServiceImpl implements MenuFunctionService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private MenuFunctionMapper menuFunctionMapper;

    @Autowired
    private MenuElementMapper menuElementMapper;

    @Autowired
    private RoleMenuElementMapper roleMenuElementMapper;

    @Autowired
    private RoleMenuFunctionMapper roleMenufunctionMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RoleMenuFunctionService roleMenufunctionService;


    @Override
    public MenuFunction getMenuFunction(Integer id) throws Exception {
        if (id == null || id <= 0) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        MenuFunction menuFunction = new MenuFunction();
        menuFunction.setId(id);
        menuFunction.setIsDelete(0);
        MenuFunction menuFunctionNew = menuFunctionMapper.selectById(id);
        if (menuFunctionNew == null) {
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }
        return menuFunctionNew;
    }

    @Override
    public Page<MenuFunctionUser> getMenuPageByType(Integer pageNo, Integer pageSize, Integer type) throws Exception {
        Page page = new Page(pageNo,pageSize);
        List<MenuFunction> menuFunctionList = menuFunctionMapper.selectMenuFunctionOrderSort(page);
        if (menuFunctionList != null && !menuFunctionList.isEmpty()) {
            List<MenuFunction> menuFunctions = new ArrayList<MenuFunction>();
            for (MenuFunction menuFunction : menuFunctionList) {
                List<MenuFunction> menuFunctionCliderList = menuFunctionMapper.selectMenuFunctionTreeById(menuFunction.getId());
                if (menuFunctionCliderList != null && !menuFunctionCliderList.isEmpty()) {
                    menuFunctions.addAll(menuFunctionCliderList);
                }
            }
            List<MenuFunctionUser> menuTree = MenuFunctionTreeUtils.getMenuFunctionTree(menuFunctions);
            if (menuTree.isEmpty()) {
                throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
            }
            page.setOptimizeCountSql(true);
            page.setRecords(menuTree);
            return page;
        } else {
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }
    }

    @Override
    public Page<MenuFunctionUser> getMenuFunctionByPage(Integer pageNo, Integer pageSize) throws Exception {
        Page page = new Page(pageNo,pageSize);
        Integer type=Integer.valueOf(RpcContext.getContext().getAttachment("loginType"));
        List<MenuFunction> menuFunctionList = menuFunctionMapper.selectMenuFunctionOrderSort(page);
        if (menuFunctionList != null && !menuFunctionList.isEmpty()) {
            List<MenuFunction> menuFunctions = new ArrayList<MenuFunction>();
            for (MenuFunction menuFunction : menuFunctionList) {
                List<MenuFunction> menuFunctionCliderList = menuFunctionMapper.selectMenuFunctionTreeById(menuFunction.getId());
                if (menuFunctionCliderList != null && !menuFunctionCliderList.isEmpty()) {
                    menuFunctions.addAll(menuFunctionCliderList);
                }
            }
            List<MenuFunctionUser> menuTree = MenuFunctionTreeUtils.getMenuFunctionTree(menuFunctions);
            if (menuTree.isEmpty()) {
                throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
            }
            page.setOptimizeCountSql(true);
            page.setRecords(menuTree);
            return page;
        } else {
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }
    }

    @Override
    public Page<RoleMenuFunctionUser> getMenuFunctionByPageWithRole(Integer pageNo, Integer pageSize, Integer roleId) throws Exception {
        if (roleId == null || roleId <= 0) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        // 获取roleId角色拥有的菜单权限数组
        List<RoleMenuFunction> roleMenufunctionList = roleMenufunctionService.getRoleMenuByRoleId(roleId);
        Page page = new Page(pageNo,pageSize);
        List<MenuFunction> menuFunctionList = menuFunctionMapper.selectMenuFunctionOrderSort(page);
        if (menuFunctionList != null && !menuFunctionList.isEmpty()) {
            List<MenuFunction> menuFunctions = new ArrayList<MenuFunction>();

            for (MenuFunction menuFunction : menuFunctionList) {
                List<MenuFunction> menuFunctionCliderList = menuFunctionMapper.selectMenuFunctionTreeById(menuFunction.getId());
                if (menuFunctionCliderList != null && !menuFunctionCliderList.isEmpty()) {
                    menuFunctions.addAll(menuFunctionCliderList);
                }
            }

            List<MenuFunctionUser> menuTree = MenuFunctionTreeUtils.getMenuFunctionTree(menuFunctions);
            List<RoleMenuFunctionUser> roleMenuTree = new ArrayList<RoleMenuFunctionUser>();

            for (int i = 0; i < menuTree.size(); i++) {
                RoleMenuFunctionUser roleMenuUser = new RoleMenuFunctionUser();
                MenuFunctionUser menuFunction = menuTree.get(i);
                if (menuFunction.getMenuFunctionChilders() != null && menuFunction.getMenuFunctionChilders().size()>0) { // 是否有子数组
                    Boolean childrenCheckedFull = true; // 子数组中是所有元素都选中--用于判断父菜单是否做全选标志
                    Boolean childrenCheckedNone = true; // 子数组中是所有元素都未选中--用于判断父菜单是否做半选标志

                    List<RoleMenuFunctionUser> childrenList = new ArrayList<RoleMenuFunctionUser>();
                    for (int j = 0; j < menuFunction.getMenuFunctionChilders().size(); j++) {
                        RoleMenuFunctionUser subRoleMenu = new RoleMenuFunctionUser();
                        MenuFunctionUser subMenu = menuFunction.getMenuFunctionChilders().get(j);
                        // 加checked
                        if (roleMenufunctionList != null && !roleMenufunctionList.isEmpty()) {
                            subRoleMenu.setChecked(this.contains(roleMenufunctionList, subMenu.getId()));
                            childrenCheckedNone = false;
                        }else {
                            subRoleMenu.setChecked(false);
                            childrenCheckedFull = false;
                        }
                        subRoleMenu.setName(subMenu.getName());
                        subRoleMenu.setId(subMenu.getId());

                        childrenList.add(subRoleMenu);
                    }

                    // 给父菜单加checked 和 halfChecked标志
                    if (childrenCheckedFull == true || childrenCheckedNone == true) {
                        roleMenuUser.setHalfChecked(false);
                    } else {
                        roleMenuUser.setHalfChecked(true);
                    }

                    // 加checked
                    if (roleMenufunctionList != null && !roleMenufunctionList.isEmpty()) {
                        roleMenuUser.setChecked(this.contains(roleMenufunctionList, menuFunction.getId()));
                    }else {
                        roleMenuUser.setChecked(false);
                    }


                    roleMenuUser.setId(menuFunction.getId());
                    roleMenuUser.setName(menuFunction.getName());
                    roleMenuUser.setChildren(childrenList);
                }else {
                    // 加checked
                    if (roleMenufunctionList != null && !roleMenufunctionList.isEmpty()) {
                        roleMenuUser.setChecked(this.contains(roleMenufunctionList, menuFunction.getId()));
                    }else {
                        roleMenuUser.setChecked(false);
                    }
                    // 判断是否选中
                    roleMenuUser.setId(menuFunction.getId());
                    roleMenuUser.setName(menuFunction.getName());
                }

                roleMenuTree.add(roleMenuUser);
            }

            if (roleMenuTree.isEmpty()) {
                throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
            }
            page.setOptimizeCountSql(true);
            page.setRecords(roleMenuTree);
            return page;
        } else {
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }

    }

    private Boolean contains(List<RoleMenuFunction> list, Integer obj) {
        Integer size = list.size();
        for (RoleMenuFunction roleMenu:list
             ) {
            if (roleMenu.getmId().equals(obj)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Boolean updateMenuFunctionById(MenuFunction menuFunction) throws Exception {
        if (menuFunction == null) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        if (menuFunction.getId() == null) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        if(menuFunction.getPid()!=null){
            if(-1==menuFunction.getPid()){
                menuFunction.setPath(menuFunction.getId().toString());
            }else {
                MenuFunction menuFunctionP = new MenuFunction();
                menuFunctionP.setId(menuFunction.getPid());
                menuFunctionP.setIsDelete(0);
                menuFunctionP = menuFunctionMapper.selectOne(new QueryWrapper<>(menuFunctionP));
                String path = null;
                if (menuFunctionP != null && StringUtils.isNotBlank(menuFunctionP.getPath())) {
                    path = menuFunctionP.getPath().concat("," + menuFunction.getId());
                } else {
                    path = menuFunction.getId().toString();
                }
                menuFunction.setPath(path);
            }
        }
        menuFunction.setGmtModified(new Date());
        int modifyUser= Integer.valueOf(RpcContext.getContext().getAttachment("id"));
        menuFunction.setModifyUser(modifyUser);
        int count = menuFunctionMapper.updateById(menuFunction);
        if (count > 0) {
            if(StringUtils.isNotBlank(menuFunction.getUrl())){
                //更新内容shrio里面内容
                redisTemplate.convertAndSend(StringConstant.REDIS_SHRIO_PERMISSION_TPOIC,StringConstant.REDIS_SHRIO_PERMISSION_TPOIC);
            }
            return true;
        } else {
            throw new ErrorException(ErrorCode.SYS_ERROR_DATABASEFAIL);
        }
    }

    @Override
    @Transactional
    public Boolean deleteMenuFunctionById(Integer id) throws Exception {
        if (id == null || id <= 0) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        List<Integer> mIdList = menuFunctionMapper.getMenuFunctionChilders(id);
        if (mIdList != null && !mIdList.isEmpty()) {
            int count = menuFunctionMapper.updateLogicallyDeleteChilders(id);
            if (count > 0) {
                //关联逻辑删除菜单_角色关联的按钮
                roleMenufunctionMapper.updateRoleFunctionDeleteByeId(mIdList);
                //关联逻辑删除当前菜单拥有的按钮
                int eCount = menuElementMapper.updateMenuElementDelete(mIdList);
                if (eCount > 0) {
                    //逻辑删除角色_按钮
                    roleMenuElementMapper.updateLogicallyDeleteBymenuElementId(mIdList);
                }
                return true;
            }
        }
        //暂无可更新内容
        throw new ErrorException(ErrorCode.SYS_ERROR_NOT_AVAILABLE);
    }

    @Override
    @Transactional
    public MenuFunction addMenuFunction(MenuFunction menuFunction) throws Exception {
        if (menuFunction == null) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        menuFunction.setIsDelete(0);
        int count = menuFunctionMapper.selectCount(new QueryWrapper<>(menuFunction));
        if(count < 0){
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }
        Date date = new Date();
        menuFunction.setGmtCreate(date);
        menuFunction.setGmtModified(date);
        int modifyUser= Integer.valueOf(RpcContext.getContext().getAttachment("id"));
        menuFunction.setModifyUser(modifyUser);
        menuFunction.setPath("-");
        count = menuFunctionMapper.insert(menuFunction);
        if (count > 0) {
            //更新path
            if(-1==menuFunction.getPid()){
                menuFunction.setPath(menuFunction.getId().toString());
            }else{
                MenuFunction menuFunctionP = new MenuFunction();
                menuFunctionP.setId(menuFunction.getPid());
                menuFunctionP.setIsDelete(0);
                menuFunctionP=menuFunctionMapper.selectOne(new QueryWrapper<>(menuFunctionP));
                String path = null;
                if(menuFunctionP!=null&&StringUtils.isNotBlank(menuFunctionP.getPath())){
                    path = menuFunctionP.getPath().concat(","+menuFunction.getId());
                }else{
                    path = menuFunction.getId().toString();
                }
                menuFunction.setPath(path);

            }
            menuFunctionMapper.updateById(menuFunction);
            return menuFunction;
        } else {
            throw new ErrorException(ErrorCode.SYS_ERROR_DATABASEFAIL);
        }
    }

    @Override
    public Page<MenuFunction> searchMenuFunctionByName(String name, Integer pageNo, Integer pageSize, String pid) throws Exception {
        if ( DataUtils.EmptyOrNegativeOrZero(pageNo, pageSize)) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        Page<MenuFunction> page = new Page<MenuFunction>(pageNo,pageSize);
        List<MenuFunction> menuFunctionList = menuFunctionMapper.searchMenuFunctionByName(page,pid,name);
        if (menuFunctionList != null && !menuFunctionList.isEmpty()) {
            page.setRecords(menuFunctionList);
            return page;
        }
        throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
    }

    @Override
    public Page<MenuFunction> getMenuFunctionListByPage(Integer pageNo, Integer pageSize) throws Exception {
        Page<MenuFunction> page = new Page<>(pageNo,pageSize);
        page = (Page<MenuFunction>) menuFunctionMapper.selectPage(page,null);
        if (page != null) {
            return page;
        }
        throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
    }

    @Override
    public Integer refreshMenu() {
        redisTemplate.convertAndSend(StringConstant.REDIS_SHRIO_PERMISSION_TPOIC,StringConstant.REDIS_SHRIO_PERMISSION_TPOIC);
        return 1;
    }

    @Override
    public Boolean refreshAuthority() throws Exception {
        //更新内容shrio里面内容
        redisTemplate.convertAndSend(StringConstant.REDIS_SHRIO_PERMISSION_TPOIC, StringConstant.REDIS_SHRIO_PERMISSION_TPOIC);
        return true;
    }
}
